home *** CD-ROM | disk | FTP | other *** search
/ Merciful 2 / Merciful - Disc 2.iso / software / d / dustv1.91.lha / Dust / Tutorial3 / Source / PExample.mod < prev    next >
Text File  |  1994-09-27  |  14KB  |  366 lines

  1. (*
  2. ###############################################################################
  3. #                                                                             #
  4. #                 Dust V1.04 - Copyright ©1994 by A.Maschke                   #
  5. #                           All rights reserved.                              #
  6. #-----------------------------------------------------------------------------#
  7. #                                                                             #
  8. #              Tutorial 3: Create a particle-explosion using Dust             #
  9. #                            -changes only particle-positions                 #
  10. #                            -writes scriptfile to stdout                     #
  11. #                                                                             #
  12. # OPERATION: 1. write a script which creates a particle-object and outputs    #
  13. #               the PPOS-array and OCOUNT, e.g.:                              #
  14. #                "load(1,objects/s1)                                          #
  15. #                 load(2,objects/c1)                                          #
  16. #                 o2p(1,2,1,p)                                                #
  17. #                 savep(1,PExample.obj)                                       #
  18. #                 getocount(1)                                                #
  19. #                 !copy T:Dust.output PExample.oCount                         #
  20. #                 getppos(1)                                                  #
  21. #                 !copy T:Dust.output PExample.PPOS                           #
  22. #                 !delete T:Dust.output                                       #
  23. #                 exit"                                                       #
  24. #             2. execute this script using Dust                               #
  25. #             3. execute this programm writing "PExample >pex.bat"            #
  26. #             4. execute the created file "pex.bat" using Dust"               #
  27. #             5. That's it (You got 12 particle objects).                     #
  28. #                                                                             #
  29. #-----------------------------------------------------------------------------#
  30. #                                                                             #
  31. #      Language: OBERON 2                                                     #
  32. #      Compiler: Amiga OBERON V3.2                                            #
  33. # Last modified: 23 September 1994                                            #
  34. #                                                                             #
  35. ###############################################################################
  36. *)
  37.  
  38. (*******************************************************************************)
  39. (* NOTE: This code is Public Domain. You can do what you want with it. *)
  40. (*******************************************************************************)
  41.  
  42. MODULE PExample;
  43. IMPORT
  44.  io,
  45.  Break,
  46.  SYS:SYSTEM,
  47.  ST:Strings,
  48.  RND:Random,
  49.  ML:MATHLIB,
  50.  MT:MathTrans,
  51.  Dos,
  52.  Exec;
  53.  
  54. (* Notes for C-Programmers:
  55.  
  56.     "IMPORT" means here "#include"
  57.  
  58.        io: stdio.h
  59.     Break: not necessary
  60.       SYS: not necessary ( "SYS.ADR(xy)" means "&xy" )
  61.        ST: string-operations ( needed to generate filenames like "obj.0521" )
  62.       RND: compute random-numbers (stdlib.h ?)
  63.        ML: math.h
  64.        MT: math.h
  65.       Dos: you will know ( "Dos.ReadAPTR()" means "Read()" )
  66.      Exec:      ""
  67. *)
  68.  
  69. CONST
  70.  ZERO=0.0001;
  71.  
  72. TYPE STRING=ARRAY 256 OF CHAR;
  73. TYPE Vector=STRUCT
  74.  x,y,z:REAL;
  75. END;
  76. TYPE VP=POINTER TO ARRAY OF Vector;
  77.  
  78. VAR
  79.  EXFILE:STRING; (* filename for the external data *)
  80.  oCount:INTEGER; (* number of particles (to be read) *)
  81.  pos:VP; (* particle positions (to be read) *)
  82.  bb:REAL; (* needed by RND2() *)
  83.  
  84. (*******************************************************************************)
  85. (* some OBERON-specific procedures ( implement them in another way *)
  86. (*******************************************************************************)
  87.  
  88. (* converts digit into CHAR *)
  89. PROCEDURE gs(lt:LONGINT):CHAR; BEGIN CASE lt OF 0:RETURN '0' | 1:RETURN '1' | 2:RETURN '2' | 3:RETURN '3' | 4:RETURN '4' | 5:RETURN '5' | 6:RETURN '6' | 7:RETURN '7' | 8:RETURN '8' | 9:RETURN '9' ELSE RETURN '0' END; END gs;
  90.  
  91. (* converts INTEGER into ARRAY OF CHAR
  92.    (aim: no spaces) *)
  93. PROCEDURE IntToString(lt:LONGINT;VAR str:STRING); VAR lt2,len,i,ll,dd:LONGINT; sig:BOOLEAN; BEGIN IF lt<0 THEN sig:=TRUE ELSE sig:=FALSE END;lt2:=ABS(lt); IF lt2=0 THEN str:="0";RETURN; (* fastest way (log10 doesn't work at 10,100,... !)*) ELSIF lt2=10 THEN str:="10";ELSIF lt2=100 THEN str:="100"; ELSIF lt2=1000 THEN str:="1000";ELSIF lt2=10000 THEN str:="10000"; ELSIF lt2=100000 THEN str:="100000";ELSIF lt2=1000000 THEN str:="1000000"; ELSIF lt2=10000000 THEN str:="10000000";ELSIF lt2=100000000 THEN str:="100000000"; ELSIF lt2=1000000000 THEN str:="1000000000"; ELSE len:=ENTIER(ML.LOG10(lt2))+1;dd:=1; IF len>1 THEN i:=1; REPEAT dd:=dd*10; INC(i); UNTIL i>=len; ELSE str[0]:=gs(lt2); str[1]:='\o'; IF sig THEN ST.InsertChar(str,0,'-') END; RETURN; END; i:=0; REPEAT ll:=lt2 DIV dd; lt2:=lt2 MOD dd; dd:=dd DIV 10; str[i]:=gs(ll); INC(i); UNTIL i>=len; str[len]:='\o'; END; IF sig THEN ST.InsertChar(str,0,'-') END; END IntToString;
  94.  
  95. (* writes an INTEGER to stdout *)
  96. PROCEDURE WriteInt(lt:LONGINT); VAR hs:STRING; BEGIN IntToString(lt,hs); io.WriteString(hs); END WriteInt;
  97.  
  98. (* converts REAL into ARRAY OF CHAR
  99.    (aim: no spaces, upto 4 digits after the point *)
  100. PROCEDURE RealToString(rt:REAL;VAR str2:STRING); VAR rt2:REAL; sig:BOOLEAN; hs:STRING; lt1,lt2,lt3:LONGINT;BEGIN IF rt=0.0 THEN str2:="0";RETURN END; IF rt<0.0 THEN sig:=TRUE ELSE sig:=FALSE END; rt2:=ABS(rt); lt1:=ENTIER(rt2); IntToString(lt1,str2); rt2:=rt2-lt1; IF rt2>=0.00005 THEN rt2:=rt2*10000.0; lt2:=ENTIER(rt2+0.5); IF lt2>=9999 THEN INC(lt1); IntToString(lt1,str2); ELSE ST.Append(str2,"."); lt3:=1; IF (lt2 MOD 10)=0 THEN lt2:=lt2 DIV 10;lt3:=10; END; IF (lt2 MOD 10)=0 THEN lt2:=lt2 DIV 10;lt3:=100; END; IF (lt2 MOD 10)=0 THEN lt2:=lt2 DIV 10;lt3:=1000; END; IntToString(lt2,hs); lt2:=lt2*lt3; IF lt2<10 THEN ST.Append(str2,"000") ELSIF lt2<100 THEN ST.Append(str2,"00") ELSIF lt2<1000 THEN ST.Append(str2,"0") ELSE END; ST.Append(str2,hs); END; END; IF sig THEN IF (str2[0]='0') AND (ST.Length(str2)=1) THEN ELSE ST.InsertChar(str2,0,'-') END; END; END RealToString;
  101.  
  102. (* writes a REAL to stdout *)
  103. PROCEDURE WriteReal(rt:REAL); VAR hs:STRING; BEGIN RealToString(rt,hs);io.WriteString(hs); END WriteReal;
  104.  
  105. (* returns a factor between 0.9 and 1.0 *)
  106. PROCEDURE RND2*():REAL; BEGIN bb:=RND.RND(901)+100; bb:=bb/10000.0; IF RND.RND(2)=1 THEN RETURN 1.0+bb ELSE RETURN 1.0-bb END; END RND2;
  107.  
  108. (* generates a filename like "obj.0235" *)
  109. PROCEDURE GenFn(str1:STRING;VAR str2:STRING;tt:INTEGER); VAR hs:STRING; BEGIN str2:=str1; IntToString(tt,hs); IF tt>=1000 THEN ST.Append(str2,".");ST.Append(str2,hs); ELSIF (tt<1000) AND (tt>=100) THEN ST.Append(str2,".0");ST.Append(str2,hs); ELSIF (tt<100) AND (tt>=10) THEN ST.Append(str2,".00");ST.Append(str2,hs); ELSIF tt<10 THEN ST.Append(str2,".000");ST.Append(str2,hs) END; END GenFn;
  110.  
  111. (*******************************************************************************)
  112. (* Read (x,y,z)-array from EXFILE; this example: pos *)
  113. (*******************************************************************************)
  114.  
  115. PROCEDURE ReadReal(fn:STRING;VAR vp:VP;count:INTEGER):BOOLEAN;
  116. VAR
  117.  a1,size,buffer:LONGINT;
  118.  fh:Dos.FileHandlePtr;
  119. BEGIN
  120.  (* allocate the array *)
  121.  IF vp#NIL THEN DISPOSE(vp) END;
  122.  SYS.ALLOCATE(vp,count);
  123.  IF vp=NIL THEN RETURN FALSE END;
  124.  (* allocate file-buffer *)
  125.  size:=LONG(count)*12; (* 3*REAL=3*4 *)
  126.  buffer:=Exec.AllocMem(size,LONGSET{Exec.public});
  127.  IF buffer=NIL THEN DISPOSE(vp);RETURN FALSE END;
  128.  (* read the file *)
  129.  fh:=Dos.Open(fn,Dos.oldFile);
  130.  IF fh=NIL THEN DISPOSE(vp);Exec.FreeMem(buffer,size);RETURN FALSE END;
  131.  a1:=Dos.ReadAPTR(fh,buffer,size);
  132.  IF Dos.Close(fh) THEN END;
  133.  IF size#a1 THEN DISPOSE(vp);Exec.FreeMem(buffer,size);RETURN FALSE END;
  134.  (* copy the buffer into the array *)
  135.  a1:=SYS.ADR(vp^[0]);
  136.  Exec.CopyMemAPTR(buffer,a1,size);
  137.  Exec.FreeMem(buffer,size);
  138.  RETURN TRUE;
  139. END ReadReal;
  140.  
  141. (*******************************************************************************)
  142. (* Read a integer from EXFILE; this example: oCount *)
  143. (*******************************************************************************)
  144.  
  145. PROCEDURE ReadInt(fn:STRING;VAR i:INTEGER):BOOLEAN;
  146. VAR
  147.  ai:LONGINT;
  148.  fh:Dos.FileHandlePtr;
  149. BEGIN
  150.  ai:=SYS.ADR(i);
  151.  fh:=Dos.Open(fn,Dos.oldFile);
  152.  IF fh=NIL THEN RETURN FALSE END;
  153.  IF Dos.ReadAPTR(fh,ai,2)#2 THEN IF Dos.Close(fh) THEN END;RETURN FALSE END;
  154.  IF Dos.Close(fh) THEN END;
  155.  RETURN TRUE;
  156. END ReadInt;
  157.  
  158. (*******************************************************************************)
  159. (* Call the SETPxxx-Procedure of Dust to change the vector vp^[ind];  *)
  160. (* this example: SETPPOS(1,ind,pos^[ind].x,pos^[ind].x,pos^[ind].z) *)
  161. (*******************************************************************************)
  162.  
  163. PROCEDURE WritePXXX(x,y,z:REAL;ind:INTEGER;cmd:STRING);
  164. BEGIN
  165.  io.WriteString("\nSETP");
  166.  io.WriteString(cmd);
  167.  io.WriteString("(1,");
  168.  WriteInt(ind);
  169.  io.WriteString(",");
  170.  WriteReal(x);
  171.  io.WriteString(",");
  172.  WriteReal(y);
  173.  io.WriteString(",");
  174.  WriteReal(z);
  175.  io.WriteString(")");
  176. END WritePXXX;
  177.  
  178. (*******************************************************************************)
  179. (* Main procedure *)
  180. (*  Arguments:
  181.      frames: number of objects (frames)
  182.          fn: base filename of the objects
  183.       timep: time to process
  184.          gp: gravity constant, e.g. -10.0 (negative)
  185.        etap: friction (Stokes), e.g. -0.00001 (negative)
  186.        vv0p: speed at t=0 (positive)
  187.         fmt: save-format-string, e.g. "TDDD"
  188. *)
  189. (*******************************************************************************)
  190.  
  191. PROCEDURE DoIt(frames:INTEGER;fn:STRING;timep,gp,etap,vv0p:REAL;fmt:STRING);
  192.  
  193. VAR
  194.  fn2:STRING;
  195.  v0:VP;
  196.  i,j:INTEGER;
  197.  oldX,oldY:POINTER TO ARRAY OF REAL;
  198.  eta,g,vv0,time,timestep,t,A,Ae,Aet,V0,X0:REAL;
  199.  centreX,centreY,centreZ:REAL;
  200.  dx,dy,dz,vb,cx,cy,cz,newX,newY,newZ:REAL;
  201.  
  202.  (*******************************************************************************)
  203.  (* calculates centre of all poarticles *)
  204.  (*******************************************************************************)
  205.  
  206.  PROCEDURE getCentre;
  207.  VAR
  208.   xmin,xmax,ymin,ymax,zmin,zmax:REAL;
  209.  BEGIN
  210.   xmin:=pos^[0].x;xmax:=xmin;ymin:=pos^[0].y;ymax:=ymin;zmin:=pos^[0].z;zmax:=zmin;
  211.   i:=1;
  212.   REPEAT
  213.    IF xmin>pos^[i].x THEN xmin:=pos^[i].x END;IF xmax<pos^[i].x THEN xmax:=pos^[i].x END;
  214.    IF ymin>pos^[i].y THEN ymin:=pos^[i].y END;IF ymax<pos^[i].y THEN ymax:=pos^[i].y END;
  215.    IF zmin>pos^[i].z THEN zmin:=pos^[i].z END;IF zmax<pos^[i].z THEN zmax:=pos^[i].z END;
  216.    INC(i);
  217.   UNTIL i>=oCount;
  218.   centreX:=xmin+(xmax-xmin)/2.0;
  219.   centreY:=ymin+(ymax-ymin)/2.0;
  220.   centreZ:=zmin+(zmax-zmin)/2.0;
  221.   (* move the object into the positive z-space if necessary *)
  222.   IF (zmin<0) AND (g#0.0) THEN
  223.    xmin:=1.1*zmin;
  224.    i:=0;
  225.    REPEAT
  226.     pos^[i].z:=pos^[i].z-xmin;
  227.     INC(i);
  228.    UNTIL i>=oCount;
  229.    zmin:=zmin-xmin;
  230.    zmax:=zmax-xmin;
  231.    (* update centreX *)
  232.    centreZ:=zmin+(zmax-zmin)/2.0;
  233.    (* change the original object *)
  234.    io.WriteString("\n;move the object into the positive z-space");
  235.    i:=0;
  236.    REPEAT
  237.     WritePXXX(pos^[i].x,pos^[i].y,pos^[i].z,i,"POS");
  238.     INC(i);
  239.    UNTIL i>=oCount;
  240.   END;
  241.  END getCentre;
  242.  
  243. BEGIN
  244.  IF (frames<1) THEN RETURN END;
  245.  (* allocate some arrays *)
  246.  SYS.ALLOCATE(v0,oCount);IF v0=NIL THEN RETURN END;
  247.  SYS.ALLOCATE(oldX,oCount);IF oldX=NIL THEN DISPOSE(v0);RETURN END;
  248.  SYS.ALLOCATE(oldY,oCount);IF oldY=NIL THEN DISPOSE(oldX);DISPOSE(v0);RETURN END;
  249.  time:=timep;
  250.  g:=gp;
  251.  eta:=etap;
  252.  vv0:=vv0p;
  253.  IF g>0.0 THEN g:=-10.0 END;
  254.  IF vv0<ZERO THEN vv0:=1.0 END;
  255.  IF eta>=0.0 THEN eta:=-0.00001 END;
  256.  getCentre;
  257.  
  258.  (* compute speed at t=0 (vectors) *)
  259.  i:=0;
  260.  REPEAT
  261.   dx:=pos^[i].x-centreX;
  262.   dy:=pos^[i].y-centreY;
  263.   dz:=pos^[i].z-centreZ;
  264.   vb:=MT.Sqrt(dx*dx+dy*dy+dz*dz);
  265.   v0^[i].x:=dx/vb*vv0*RND2();
  266.   v0^[i].y:=dy/vb*vv0*RND2();
  267.   v0^[i].z:=dz/vb*vv0*RND2();
  268.   INC(i);
  269.  UNTIL i>=oCount;
  270.  
  271.  (* generate filename and say "save it" (first and unchanged object) *)
  272.  GenFn(fn,fn2,1);
  273.  IF fmt="TDDD" THEN io.WriteString("\nSavePTDDD(1,");
  274.  ELSIF fmt="VS" THEN io.WriteString("\nSavePVS(1,");
  275.  ELSE io.WriteString("\nSaveP(1,");
  276.  END;
  277.  io.WriteString(fn2);io.WriteString(")");
  278.  
  279.  (* main loop *)
  280.  timestep:=time/(frames-1);
  281.  i:=1;
  282.  REPEAT
  283.  
  284.   (* output frame as comment *)
  285.   io.WriteString("\n;frame ");WriteInt(i);
  286.  
  287.   t:=i*timestep; (* actual time *)
  288.   j:=0;
  289.   REPEAT
  290.  
  291.    (* particle-size (friction) (to calculate this the array PSCL is needed) *)
  292.    A:=RND2()*10.0;
  293.    Ae:=A*eta;
  294.    Aet:=Ae*t;
  295.  
  296.    (* compute x-coordinate *)
  297.    V0:=v0^[j].x;
  298.    X0:=pos^[j].x;
  299.    cx:=(X0*Ae-V0+V0*MT.Exp(Aet))/(Ae);
  300.  
  301.    (* compute y-coordinate *)
  302.    V0:=v0^[j].y;
  303.    X0:=pos^[j].y;
  304.    cy:=(X0*Ae-V0+V0*MT.Exp(Aet))/(Ae);
  305.  
  306.    (* compute x-coordinate *)
  307.    V0:=v0^[j].z;
  308.    X0:=pos^[j].z;
  309.    cz:=(X0*Ae*Ae-g-V0*Ae+g*MT.Exp(Aet)+V0*Ae*MT.Exp(Aet)-g*t*Ae)/(Ae*Ae);
  310.  
  311.    (* motion must stop at z=0 *)
  312.    IF cz>0.0 THEN
  313.     oldX^[j]:=cx;
  314.     oldY^[j]:=cy;
  315.    ELSE
  316.     cz:=0.0;
  317.     IF i>1 THEN
  318.      cx:=oldX^[j];
  319.      cy:=oldY^[j];
  320.     ELSE
  321.      oldX^[j]:=cx;
  322.      oldY^[j]:=cy;
  323.     END;
  324.    END;
  325.  
  326.    (* the final posion *)
  327.    newX:=cx;
  328.    newY:=cy;
  329.    newZ:=cz;
  330.  
  331.    (* say: "apply them" *)
  332.    WritePXXX(newX,newY,newZ,j,"POS");
  333.  
  334.    INC(j);
  335.   UNTIL j>=oCount;
  336.  
  337.   (* generate filename and say "save it" *)
  338.   GenFn(fn,fn2,i+1);
  339.   IF fmt="TDDD" THEN io.WriteString("\nSavePTDDD(1,");
  340.   ELSIF fmt="VS" THEN io.WriteString("\nSavePVS(1,");
  341.   ELSE io.WriteString("\nSaveP(1,"); END;
  342.   io.WriteString(fn2); io.WriteString(")");
  343.  
  344.   INC(i);
  345.  UNTIL  i>=frames;
  346.  
  347.  (* clean up *)
  348.  DISPOSE(oldY);DISPOSE(oldX);
  349.  DISPOSE(v0);
  350. END DoIt;
  351.  
  352. BEGIN
  353.  (* load the ppos-array *)
  354.  IF ReadInt("PEXAMPLE.OCOUNT",oCount) AND ReadReal("PEXAMPLE.PPOS",pos,oCount) THEN
  355.   (* tell Dust to load the Source-Particle-Object *)
  356.   io.WriteString("\nloadp(1,PExample.obj)");
  357.   (* do it !*)
  358.   DoIt(12,"obj",12.8,-10.0,-0.001,52,"TDDD");
  359.   (* important*)
  360.   io.WriteString("\n");
  361.   DISPOSE(pos);
  362.  ELSE
  363.   io.WriteString("\nCouldn't open input-file(s).\n");
  364.  END;
  365. END PExample.
  366.